

package cn.shengchao.examstar.account.ohs.local.appservice;

import cn.hutool.extra.spring.SpringUtil;
import cn.shengchao.examstar.account.acl.ports.repositories.IAccountRepository;
import cn.shengchao.examstar.account.acl.ports.repositories.IBankCardRepository;
import cn.shengchao.examstar.account.domain.Account;
import cn.shengchao.examstar.account.domain.AccountPayLog;
import cn.shengchao.examstar.account.domain.AccountPayoutsLog;
import cn.shengchao.examstar.account.domain.BankCard;
import cn.shengchao.examstar.account.ohs.local.appservice.message.AccountDto;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.continew.starter.core.exception.BusinessException;
import top.continew.starter.core.validation.CheckUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

@Service
public class AccountAppService {

    @Autowired
    private IAccountRepository accountRepository;

    @Autowired
    private IBankCardRepository iBankCardRepository;

    public void transferToFreezeBalance(Long accountId,
                                        String orderId,
                                        BigDecimal price,
                                        String remarks,
                                        String sourceType) {
        RedissonClient CLIENT = SpringUtil.getBean(RedissonClient.class);
        RLock lock = CLIENT.getLock("account_transfer" + accountId);
        lock.lock();
        try {
            //更新账户冻结余额
            Account account = accountRepository.of(accountId);
            account.setBalance(account.getBalance().add(price));
            account.setFrozenBalance(account.getFrozenBalance().add(price));
            accountRepository.update(account);
            //记录交易流水
            AccountPayLog accountPayLog = new AccountPayLog();
            accountPayLog.setAccountId(accountId);
            accountPayLog.setSourceType(sourceType);
            accountPayLog.setBalance(account.getBalance());
            accountPayLog.setAmount(price);
            accountPayLog.setType("1");
            accountPayLog.setRemark(remarks);
            accountPayLog.setBalance(account.getBalance());
            accountPayLog.setTime(new Date());
            accountPayLog.setPayNumber(orderId);
            accountPayLog.setUserId(account.getUserId());
            accountRepository.saveAccountPayLog(accountPayLog);
        } finally {
            lock.unlock();
        }
    }

    public void transferFreezeBalanceToBalance(Long accountId, Long linkOrderId, BigDecimal amount) {
        RedissonClient CLIENT = SpringUtil.getBean(RedissonClient.class);
        RLock lock = CLIENT.getLock("account_transfer" + accountId);
        lock.lock();
        try {
            //更新账户冻结余额
            Account account = accountRepository.of(accountId);
            //减少冻结金额
            account.setFrozenBalance(account.getFrozenBalance().subtract(amount));
            //增加可提现余额
            account.setWithdrawBalance(account.getWithdrawBalance().add(amount));
            accountRepository.update(account);
            //记录交易流水
            AccountPayLog accountPayLog = new AccountPayLog();
            accountPayLog.setAccountId(accountId);
            accountPayLog.setAmount(amount);
            accountPayLog.setSourceType("冻结");
            accountPayLog.setBalance(account.getBalance());
            accountPayLog.setType("2");
            accountPayLog.setTime(new Date());
            accountPayLog.setBalance(account.getBalance());
            accountPayLog.setPayNumber(String.valueOf(linkOrderId));
            accountPayLog.setUserId(account.getUserId());
            accountRepository.saveAccountPayLog(accountPayLog);
        } finally {
            lock.unlock();
        }
    }

    public AccountDto balance(Long uid) {
        Optional<Account> accountOptional = accountRepository.ofByUid(uid);

        if (accountOptional.isEmpty()) {
            return new AccountDto();
        }
        AccountDto accountDto = new AccountDto();
        Account account = accountOptional.get();
        accountDto.setId(account.getId());
        accountDto.setBalance(account.getBalance());
        accountDto.setFrozenBalance(account.getFrozenBalance());
        accountDto.setWithdrawBalance(account.getWithdrawBalance());
        accountDto.setPointsBalance(account.getPointsBalance());
        BigDecimal yesterdayIncome = accountRepository.getYesterdayIncome(account.getId());
        accountDto.setYesterdayIncome(yesterdayIncome);
        return accountDto;
    }

    public void withdraw(Long uid, BigDecimal amount, String backCardId) {
        CheckUtils.throwIf(amount.doubleValue() < 100, "提现金额不能小于100");
        Optional<Account> accountOptional = accountRepository.ofByUid(uid);
        Account account = accountOptional.orElseThrow(() -> new BusinessException("可提现金额不足！"));
        CheckUtils.throwIf(account.getWithdrawBalance().compareTo(amount) < 0, "可提现金额不足！");
        Optional<BankCard> backCardOptional = iBankCardRepository.findById(backCardId);
        BankCard bankCard = backCardOptional.orElseThrow(() -> new BusinessException("银行卡不存在！"));
        CheckUtils.throwIf(!Objects.equals(bankCard.getUserId(), uid), "银行卡不属于当前用户！");
        RedissonClient CLIENT = SpringUtil.getBean(RedissonClient.class);
        RLock lock = CLIENT.getLock("account_transfer" + account.getId());
        lock.lock();
        try {
            //更新账户可提现余额
            account.setBalance(account.getBalance().subtract(amount));
            account.setWithdrawBalance(account.getWithdrawBalance().subtract(amount));
            accountRepository.update(account);
            //记录交易流水
            AccountPayLog accountPayLog = new AccountPayLog();
            accountPayLog.setAccountId(account.getId());
            accountPayLog.setAmount(BigDecimal.ZERO.subtract(amount));
            accountPayLog.setSourceType("提现");
            accountPayLog.setBalance(account.getBalance());
            accountPayLog.setType("4");
            accountPayLog.setTime(new Date());
            //提现记录
            AccountPayoutsLog accountPayoutsLog = new AccountPayoutsLog();
            accountPayoutsLog.setAccountId(account.getId());
            accountPayoutsLog.setUserId(uid);
            accountPayoutsLog.setOpenId(account.getOpenId());
            accountPayoutsLog.setPayoutsAmount(amount);
            accountPayoutsLog.setStatus("0");
            accountPayoutsLog.setBalance(account.getBalance());
            accountPayoutsLog.setProcessingTime(new Date());
            accountPayoutsLog.setFiledTime(new Date());
            accountPayoutsLog.setBackCardId(backCardId);
            accountPayoutsLog.setCardNo(bankCard.getCardNo());
            accountPayoutsLog.setBankOfDeposit(bankCard.getBankOfDeposit());
            accountRepository.saveAccountPayoutsLog(accountPayoutsLog);
        } finally {
            lock.unlock();
        }
    }
}
